﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Tencent;

namespace Core.Sdk.WeiXin.Tool
{
    public class Encrypt
    {

        /// <summary>
        /// V3通知解密 (AES_256_GC 方式)
        /// </summary>
        /// <param name="keyV3">V3版秘钥</param>
        /// <param name="ciphertext">密文</param>
        /// <param name="nonce">随机数</param>
        /// <param name="associatedData">关联数据</param>
        /// <returns></returns>
        /// 
        public static string AesGcmDecrypt(string keyV3, string ciphertext, string nonce, string associatedData)
        {
            GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
            AeadParameters aeadParameters = new AeadParameters(
                new KeyParameter(Encoding.UTF8.GetBytes(keyV3)),
                128,
                Encoding.UTF8.GetBytes(nonce),
                Encoding.UTF8.GetBytes(associatedData));
            gcmBlockCipher.Init(false, aeadParameters);

            byte[] data = Convert.FromBase64String(ciphertext);
            byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
            int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
            gcmBlockCipher.DoFinal(plaintext, length);
            var text = Encoding.UTF8.GetString(plaintext);
            if (text.IndexOf("\n") > -1)
                text = text.Substring(text.IndexOf("\n"));
            if (text.LastIndexOf("\n") > -1)
                text = text.Substring(0, text.LastIndexOf("\n"));
            text = text.Replace("\n", "");
            return text;
        }


        /// <summary>
        /// 敏感信息加密(RSA算法，使用从接口下载到的公钥进行加密，非后台下载到的私钥)
        /// </summary>
        /// <param name="text">要加密的明文</param>
        /// <param name="publicKey"> -----BEGIN CERTIFICATE----- 开头的string，转为bytes </param>
        /// <returns></returns>
        public static string RSAEncrypt(string text, byte[] publicKey)
        {
            var x509 = new X509Certificate2(publicKey);
            using (var rsa = (RSACryptoServiceProvider)x509.PublicKey.Key)
            {
                var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), true);
                return Convert.ToBase64String(buff);
            }
        }

        public static string HmacSHA256(string message, string secret)
        {
            secret = secret ?? "";
            var encoding = new System.Text.UTF8Encoding();
            byte[] keyByte = encoding.GetBytes(secret);
            byte[] messageBytes = encoding.GetBytes(message);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < hashmessage.Length; i++)
                {
                    builder.Append(hashmessage[i].ToString("x2"));
                }
                return builder.ToString();
            }
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="encypStr">加密字符串</param>
        /// <param name="charset">编码方式</param>
        /// <returns></returns>
        public static string GetMD5(string encypStr, string charset = "utf-8")
        {
            string retStr;
            MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

            //创建md5对象
            byte[] inputBye;
            byte[] outputBye;

            //使用GB2312编码方式把字符串转化为字节数组．
            try
            {
                inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
            }
            catch (Exception ex)
            {
                inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
            }
            outputBye = m5.ComputeHash(inputBye);

            retStr = System.BitConverter.ToString(outputBye);
            retStr = retStr.Replace("-", "").ToUpper();
            return retStr;
        }


        public static string EncodeSHA1(SortedDictionary<string, string> listParam)
        {
            var sign = string.Empty;
            var sbParam = new StringBuilder();
            ArrayList AL = new ArrayList();

            foreach (var p in listParam)
            {
                if (string.IsNullOrEmpty(p.Value))
                    continue;
                AL.Add(p.Value);
            }

            AL.Sort(new WXBizMsgCrypt.DictionarySort());
            for (int i = 0; i < AL.Count; ++i)
            {
                sbParam.Append(AL[i]);
            }

            SHA1 sha;
            ASCIIEncoding enc;
            string hash = "";
            try
            {
                sha = new SHA1CryptoServiceProvider();
                enc = new ASCIIEncoding();
                byte[] dataToHash = enc.GetBytes(sbParam.ToString());
                byte[] dataHashed = sha.ComputeHash(dataToHash);
                hash = BitConverter.ToString(dataHashed).Replace("-", "");
                hash = hash.ToLower();
            }
            catch (Exception)
            {
            }
            sign = hash;
            return sign;
        }
    }
}
